package com.huawei.app.demo;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.huawei.app.demo.fragment.AudioFragment;
import com.huawei.app.demo.fragment.CastFragment;
import com.huawei.app.demo.fragment.CommFragment;
import com.huawei.app.demo.fragment.ConferenceFragment;
import com.huawei.app.demo.fragment.ContentPagerAdapter;
import com.huawei.app.demo.fragment.CustomFragment;
import com.huawei.app.demo.fragment.HttpApiFragment;
import com.huawei.app.demo.fragment.ImageFragment;
import com.huawei.app.demo.fragment.VideoFragment;
import com.huawei.app.demo.fragment.WhiteboardFragment;
import com.huawei.app.demo.util.BroadcastUtils;
import com.huawei.app.demo.util.LogUtils;
import com.huawei.app.demo.util.NetworkUtils;
import com.huawei.app.demo.util.SystemIconUtils;
import com.huawei.app.demo.video.HDMISurfaceCallback;
import com.huawei.app.httpapi.HttpApiResult;
import com.huawei.app.httpapi.IdeaHubHttpApiUtils;
import com.huawei.app.httpapi.ThreadPools;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();
    public static String ACTIVITY_PACKAGE_NAME = MainActivity.class.getPackage().getName();
    public static boolean IS_HDMI_CASTING = false;

    // 权限信息
    private static String[] APP_PERMISSIONS = {
            "android.permission.WRITE_EXTERNAL_STORAGE",
            "android.permission.INTERNET", "com.device.permission.THIRDAPP" };

    // 消息处理器
    private Handler msgHandler = new MsgHandler(this);

    // HTTP API
    private static final String API_SERVER = "127.0.0.1";
    private static final String API_USER = "api";
    private static final String API_PASS = "admin@1234";

    // UI控件
    private List<CustomFragment> tabFragments;
    private boolean initFinished = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化应用常量
        MainActivity.ACTIVITY_PACKAGE_NAME = getPackageName();

        boolean exitFromWhiteboard = getIntent().getBooleanExtra("EXTRA_EXIT_WHITEBOARD", false);
        LogUtils.getInstance().i(TAG, "exit from whiteboard " + exitFromWhiteboard);

        // 初始化UI控件
        initViews();

        // 申请应用需要的权限
        if (Build.VERSION.SDK_INT > 22 && !checkPermissionAllGranted(APP_PERMISSIONS)) {
            ActivityCompat.requestPermissions(MainActivity.this, APP_PERMISSIONS, AppConstants.REQUEST_PERMISSIONS_CODE);
        } else {
            initData();
            initEvent();
        }
    }

    /**
     * 检查应用需要的权限
     * @param permissions
     * @return
     */
    private boolean checkPermissionAllGranted(String[] permissions) {
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                // 只要有一个权限没有被授予, 则直接返回 false
                return false;
            }
        }
        return true;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        initData();
        initEvent();
    }

    /**
     * 初始化UI控件
     */
    private void initViews() {
        LogUtils.getInstance().i(TAG, "initViews begin.");
        TabLayout navMenuTab = findViewById(R.id.nav_menu);
        ViewPager navContent = findViewById(R.id.nav_content);

        navMenuTab.setTabMode(TabLayout.MODE_SCROLLABLE);
        navMenuTab.setTabTextColors(getResources().getColor(R.color.colorNormalText, null), getResources().getColor(R.color.colorSelectedText, null));
        navMenuTab.setSelectedTabIndicatorColor(getResources().getColor(R.color.colorPrimary, null));

        tabFragments = new ArrayList<>();
        tabFragments.add(new CommFragment());
        tabFragments.add(new HttpApiFragment());
        tabFragments.add(new ConferenceFragment());
        tabFragments.add(new WhiteboardFragment());
        tabFragments.add(new CastFragment());
        tabFragments.add(new AudioFragment());
        tabFragments.add(new VideoFragment());
        tabFragments.add(new ImageFragment());

        ContentPagerAdapter pagerAdapter = new ContentPagerAdapter(getSupportFragmentManager(), tabFragments);
        navContent.setAdapter(pagerAdapter);
        navMenuTab.setupWithViewPager(navContent);

        // 隐藏右下角panel
        LinearLayout bottomRightPanel = findViewById(R.id.bottomRightPanel);
        bottomRightPanel.setVisibility(View.GONE);
        LogUtils.getInstance().i(TAG, "initViews end.");
    }

    /**
     * 初始化UI控件的数据信息
     */
    private void initData() {
        if (initFinished) {
            return;
        }
        LogUtils.getInstance().i(TAG, "initData begin.");

        // 检测设备信息
        detectDeviceInfo();

        // 检测屏幕分辨率
        // 在onCreate方法中因view控件还没有显示到屏幕上, 获取不到真实的可视区域大小, 因此等待1秒后再获取
        detectScreenResolution(msgHandler, 1000);

        // 检测网络信息
        detectNetworkInfo();

        // 检测系统时间
        detectSystemTime();

        // 初始化HTTP API接口调用
        initHttpApi();

        // 隐藏九宫格, 工具栏, 返回键
        // SystemIconUtils.hideAllIcon(getApplicationContext());

        initFinished = true;
        LogUtils.getInstance().i(TAG, "initData end.");
    }

    /**
     * 初始化事件
     */
    private void initEvent() {
        // 初始化广播事件处理
        BroadcastUtils.initBroadcastReceiver(this);
    }

    /**
     * 检测设备信息
     */
    private void detectDeviceInfo() {
        String manufacturer = android.os.Build.MANUFACTURER; // Huawei
        String model = Build.MODEL; // IdeaHub
        String isBoardStr = getSystemPropValue("sys.device.is.board");
        if ("1".equals(isBoardStr)) {
            model = "Board";
        }
        String sn = getSystemPropValue("sys.device.sn");

        TextView deviceInfo = findViewById(R.id.deviceInfo);
        deviceInfo.setText(manufacturer + "-" + model + "-" + sn);
    }

    /**
     * 获取系统属性值
     * @param key
     * @return
     */
    private String getSystemPropValue(String key) {
        Class<?> classType = null;
        String value = "";
        try {
            classType = Class.forName("android.os.SystemProperties");
            Method getMethod = classType.getDeclaredMethod("get", new Class<?>[]{String.class});
            value = (String)getMethod.invoke(classType, new Object[]{key});
        } catch (Exception e) {
            LogUtils.getInstance().e(TAG, e.getMessage());
        }
        return value;
    }

    /**
     * 检测屏幕分辨率
     * @param handler
     * @param delay
     */
    private void detectScreenResolution(Handler handler, long delay) {
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                detectScreenResolution();
            }
        }, delay);
    }

    /**
     * 检测屏幕分辨率
     */
    private void detectScreenResolution() {
        String text = "屏幕分辨率：";
        Display display = getWindowManager().getDefaultDisplay();

        Rect rectSize = new Rect();
        display.getRectSize(rectSize);
        text += "\r\nrectSize(像素): " + rectSize.width() + " x " + rectSize.height();

        Point realSize = new Point();
        display.getRealSize(realSize);
        text += "\r\nrealSize(像素): " + realSize.x + " x " + realSize.y;

        DisplayMetrics realMetrics = new DisplayMetrics();
        display.getRealMetrics(realMetrics);
        float density = realMetrics.density;
        int dpi = realMetrics.densityDpi;
        text += "\r\nrealMetrics(像素): " + realMetrics.widthPixels + " x " + realMetrics.heightPixels;
        text += "\r\nrealMetrics(dp): " + (int)(realMetrics.widthPixels/density) + " x " + (int)(realMetrics.heightPixels/density);
        text += "\r\ndpi: " + dpi + ", density: " + density;

        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        text += "\r\ndisplayMetrics(像素): " + displayMetrics.widthPixels + " x " + displayMetrics.heightPixels;

        Display.Mode[] modes = display.getSupportedModes();
        if (modes == null) {
            Message msg = Message.obtain();
            msg.what = MsgHandler.UPDATE_VIEW_TEXT;
            msg.obj = new MsgHandler.UpdateViewText(R.id.screenInfo, text);
            msgHandler.sendMessage(msg);
            return;
        }

        Display.Mode selected = null;
        for (Display.Mode mode : modes) {
            LogUtils.getInstance().i(TAG, "show Display.Mode " + mode.getPhysicalWidth() + " x " + mode.getPhysicalHeight());
            if (selected == null) {
                selected = mode;
                continue;
            }
            if (mode.getPhysicalWidth() > selected.getPhysicalWidth()) {
                selected = mode;
            }
        }
        if (selected != null) {
            text += "\r\nDisplay.Mode: " + selected.getPhysicalWidth() + " x " + selected.getPhysicalHeight();
            WindowManager.LayoutParams params = getWindow().getAttributes();
            params.preferredDisplayModeId = selected.getModeId();

            Message msg = Message.obtain();
            msg.what = MsgHandler.UPDATE_DISPLAY_MODE;
            msg.obj = params;
            msg.arg1 = selected.getPhysicalWidth();
            msg.arg2 = selected.getPhysicalHeight();
            msgHandler.sendMessage(msg);
        }

        Rect outRect = new Rect();
        getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect);
        LogUtils.getInstance().i(TAG, "outRect " + outRect.width() + " x " + outRect.height());
        text += "\r\noutRect: " + outRect.width() + " x " + outRect.height();

        Message msg = Message.obtain();
        msg.what = MsgHandler.UPDATE_VIEW_TEXT;
        msg.obj = new MsgHandler.UpdateViewText(R.id.screenInfo, text);
        msgHandler.sendMessage(msg);
    }

    /**
     * 检测网络信息
     */
    private void detectNetworkInfo() {
        ThreadPools.run(new Runnable() {
            @Override
            public void run() {
                String ipMacInfo = NetworkUtils.getNetworkInfo();

                Message msg = Message.obtain();
                msg.what = MsgHandler.UPDATE_VIEW_TEXT;
                msg.obj = new MsgHandler.UpdateViewText(R.id.networkInfo, "网络信息：\r\n" + ipMacInfo);
                msgHandler.sendMessage(msg);
            }
        });
    }

    /**
     * 检测系统时间
     */
    private void detectSystemTime() {
        ThreadPools.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                String time = format.format(new Date());

                Message msg = Message.obtain();
                msg.what = MsgHandler.UPDATE_VIEW_TEXT;
                msg.obj = new MsgHandler.UpdateViewText(R.id.timeInfo, "系统时间：" + time);
                msgHandler.sendMessage(msg);
            }
        }, 500, 100, TimeUnit.MILLISECONDS);
    }

    /**
     * 初始化HTTP API
     */
    private void initHttpApi() {
        final String pkgName = getPackageName();
        ThreadPools.run(new Runnable(){
            private int failedCount = 0;
            private String errorMsg = "HTTP API鉴权密码错误，请在【系统配置 > 基本信息 > 用户】页面中将API鉴权密码修改为 admin@1234";
            @Override
            public void run() {
                // 初始化HTTP API接口
                HttpApiResult apiResult = IdeaHubHttpApiUtils.getInstance().login(API_SERVER, API_USER, API_PASS);

                // 登录成功则启动心跳线程
                if (apiResult.isSuccess()) {
                    LogUtils.getInstance().i(TAG, "http api login success.");
                    // 启动心跳
                    IdeaHubHttpApiUtils.getInstance().startHeartbeat();
                    // 订阅消息
                    IdeaHubHttpApiUtils.getInstance().subscribeMsg();
                    // 初始化组件状态(例如Checkbox选中状态)
                    for (CustomFragment tmpFragment : tabFragments) {
                        tmpFragment.initViewStatus();
                    }
                } else {
                    LogUtils.getInstance().i(TAG, "http api login failed.");

                    // 如果 http api 鉴权失败, 则延迟1分钟继续登录, 重试3次
                    failedCount++;
                    if (failedCount < 3) {
                        ThreadPools.schedule(this, 1, TimeUnit.MINUTES);

                        Message msg = Message.obtain();
                        msg.what = MsgHandler.SHOW_TOAST;
                        msg.obj = errorMsg;
                        msg.arg1 = Toast.LENGTH_LONG;
                        msgHandler.sendMessage(msg);
                    }
                }
            }
        });
    }

    /**
     * 投屏内容显示到右上角
     */
    public void showInTopRight() {
        LogUtils.getInstance().i(TAG, "showInTopRight begin.");

        // 先检查右上角是否存在内容
        LinearLayout topRightPanel = findViewById(R.id.topRightPanel);
        boolean hasChild = topRightPanel.getChildCount() > 0;

        // 恢复到默认状态
        resetHDMICastUI();

        // 如果右上角之前存在内容, 当前已进入隐藏状态, 这里直接返回
        if (hasChild) {
            return;
        }

        // 如果右上角之前没有内容, 则显示投屏内容
        LayoutInflater inflater = getLayoutInflater();
        View view = inflater.inflate(R.layout.cast_surface, null);
        SurfaceView castSurfaceview = view.findViewById(R.id.castSurfaceview);
        castSurfaceview.getHolder().addCallback(new HDMISurfaceCallback(castSurfaceview));

        topRightPanel.addView(view);
        LogUtils.getInstance().i(TAG, "showInTopRight end.");
    }

    /**
     * 投屏内容全屏显示
     */
    public void showInFullScreen() {
        resetHDMICastUI();

        LinearLayout mainPanel = findViewById(R.id.mainPanel);
        LayoutInflater inflater = getLayoutInflater();
        View view = inflater.inflate(R.layout.cast_surface, null);
        SurfaceView castSurfaceview = view.findViewById(R.id.castSurfaceview);
        castSurfaceview.getHolder().addCallback(new HDMISurfaceCallback(castSurfaceview));

        mainPanel.addView(view, 0);
    }

    /**
     * 重置HDMI有线投屏界面UI -- 将右上角/右下角恢复为默认状态
     */
    public void resetHDMICastUI() {
        // 恢复右上角
        LinearLayout topRightPanel = findViewById(R.id.topRightPanel);
        if (topRightPanel.getChildCount() > 0) {
            topRightPanel.removeAllViews();
        }

        // 恢复右下角
        LinearLayout bottomRightPanel = findViewById(R.id.bottomRightPanel);
        if (bottomRightPanel.getChildCount() > 0) {
            bottomRightPanel.removeAllViews();
            bottomRightPanel.setVisibility(View.GONE);
        }

        // 从全屏模式恢复
        LinearLayout mainPanel = findViewById(R.id.mainPanel);
        if (mainPanel.getChildCount() > 0) {
            String firstViewId = getResources().getResourceName(mainPanel.getChildAt(0).getId());
            if (firstViewId != null && firstViewId.endsWith("castSurfaceLayout")) {
                mainPanel.removeViewAt(0);
            }
        }
    }

    /**
     * 应用授权结果
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    public void onBackPressed() {
        // 屏蔽返回键的处理, 避免按返回键时应用退出
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        LogUtils.getInstance().close();
    }
}
